home *** CD-ROM | disk | FTP | other *** search
- /* Implements a lightweight scrollbar widget.
- Copyright (C) 1992, 1993, 1994 Lucid, Inc.
-
- This file is part of the Lucid Widget Library.
-
- The Lucid Widget Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- The Lucid Widget Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNU Emacs; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- /* Created by Douglas Keller <dkeller@vnet.ibm.com> */
- /* Last changed 03/24/95 */
-
- /*
- * Resources Supported:
- * XmNforeground
- * XmNbackground
- * XmNtopShadowColor
- * XmNtopShadowPixmap
- * XmNbottomShadowColor
- * XmNbottomShadowPixmap
- * XmNtroughColor
- * XmNshadowThickness
- * XmNshowArrows
- * XmNorientation
- * XmNborderWidth
- *
- * XmNminimum
- * XmNmaximum
- * XmNvalue
- * XmNincrement
- * XmNpageIncrement
- *
- * XmNvalueChangedCallback
- * XmNincrementCallback
- * XmNdecrementCallback
- * XmNpageIncrementCallback
- * XmNpageDecrementCallback
- * XmNtoTopCallback
- * XmNtoBottomCallback
- * XmNdragCallback
- *
- * XmNknobStyle - values can be: "plain" or "dimple"
- * XmNarrowPosition - values can be: "opposite" or "same"
- *
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <limits.h>
-
- #include <X11/IntrinsicP.h>
- #include <X11/StringDefs.h>
- #include <X11/bitmaps/gray>
-
- #include "xlwscrollbarP.h"
- #include "xlwscrollbar.h"
-
- #define DBUG(x)
-
- #define MINL(x,y) ((((unsigned long) (x)) < ((unsigned long) (y))) \
- ? ((unsigned long) (x)) : ((unsigned long) (y)))
-
- #define VERT(w) (w->sb.orientation == XmVERTICAL)
-
- #define SS_MIN 8
-
- #define ARROW_UP 0
- #define ARROW_DOWN 1
- #define ARROW_LEFT 2
- #define ARROW_RIGHT 3
-
- #define ARM_NONE 0
- #define ARM_KNOB 1
- #define ARM_UP 2
- #define ARM_DOWN 3
- #define ARM_PAGEUP 4
- #define ARM_PAGEDOWN 5
-
- #define BUTTON_NONE 0
- #define BUTTON_KNOB 1
- #define BUTTON_UP_ARROW 2
- #define BUTTON_DOWN_ARROW 3
- #define BUTTON_TROUGH_ABOVE 4
- #define BUTTON_TROUGH_BELOW 5
-
- #define KNOB_PLAIN 0
- #define KNOB_DIMPLE 1
-
- /************************************************************************
- **
- ** Resources
- **
- */
- #define offset(field) XtOffset(XlwScrollBarWidget, field)
-
- static XtResource resources[] = {
- { XmNforeground, XmCForeground, XtRPixel, sizeof(Pixel),
- offset(sb.foreground), XtRImmediate, XtDefaultForeground },
-
- { XmNtopShadowColor, XmCTopShadowColor, XtRPixel, sizeof(Pixel),
- offset(sb.topShadowColor), XtRImmediate, (XtPointer) ~0 },
- { XmNbottomShadowColor, XmCBottomShadowColor, XtRPixel, sizeof(Pixel),
- offset(sb.bottomShadowColor), XtRImmediate, (XtPointer)~0 },
-
- { XmNtopShadowPixmap, XmCTopShadowPixmap, XtRPixmap, sizeof (Pixmap),
- offset(sb.topShadowPixmap), XtRImmediate, (XtPointer)None},
- { XmNbottomShadowPixmap, XmCBottomShadowPixmap, XtRPixmap, sizeof (Pixmap),
- offset(sb.bottomShadowPixmap), XtRImmediate, (XtPointer)None},
-
- { XmNtroughColor, XmCTroughColor, XtRPixel, sizeof(Pixel),
- offset(sb.troughColor), XtRImmediate, (XtPointer)~0 },
-
- { XmNshadowThickness, XmCShadowThickness, XtRInt, sizeof(int),
- offset(sb.shadowThickness), XtRImmediate, (XtPointer)2 },
-
- { XmNborderWidth, XmCBorderWidth, XtRDimension, sizeof(Dimension),
- offset(core.border_width), XtRImmediate, (XtPointer)0 },
-
- { XmNshowArrows, XmCShowArrows, XtRBoolean, sizeof(Boolean),
- offset(sb.showArrows), XtRImmediate, (XtPointer)True },
-
- { XmNinitialDelay, XmCInitialDelay, XtRInt, sizeof(int),
- offset(sb.initialDelay), XtRImmediate, (XtPointer) 250 },
- { XmNrepeatDelay, XmCRepeatDelay, XtRInt, sizeof(int),
- offset(sb.repeatDelay), XtRImmediate, (XtPointer) 50 },
-
- { XmNorientation, XmCOrientation, XtROrientation, sizeof(unsigned char),
- offset(sb.orientation), XtRImmediate, (XtPointer) XmVERTICAL },
-
-
- { XmNminimum, XmCMinimum, XtRInt, sizeof(int),
- offset(sb.minimum), XtRImmediate, (XtPointer) 0},
- { XmNmaximum, XmCMaximum, XtRInt, sizeof(int),
- offset(sb.maximum), XtRImmediate, (XtPointer) 100},
- { XmNvalue, XmCValue, XtRInt, sizeof(int),
- offset(sb.value), XtRImmediate, (XtPointer) 0},
- { XmNsliderSize, XmCSliderSize, XtRInt, sizeof(int),
- offset(sb.sliderSize), XtRImmediate, (XtPointer) 10},
- { XmNincrement, XmCIncrement, XtRInt, sizeof(int),
- offset(sb.increment), XtRImmediate, (XtPointer) 1},
- { XmNpageIncrement, XmCPageIncrement, XtRInt, sizeof(int),
- offset(sb.pageIncrement), XtRImmediate, (XtPointer) 10},
-
- { XmNvalueChangedCallback, XmCValueChangedCallback, XtRCallback, sizeof(XtPointer),
- offset(sb.valueChangedCBL), XtRCallback, NULL},
- { XmNincrementCallback, XmCIncrementCallback, XtRCallback, sizeof(XtPointer),
- offset(sb.incrementCBL), XtRCallback, NULL},
- { XmNdecrementCallback, XmCDecrementCallback, XtRCallback, sizeof(XtPointer),
- offset(sb.decrementCBL), XtRCallback, NULL},
- { XmNpageIncrementCallback, XmCPageIncrementCallback, XtRCallback, sizeof(XtPointer),
- offset(sb.pageIncrementCBL), XtRCallback, NULL},
- { XmNpageDecrementCallback, XmCPageDecrementCallback, XtRCallback, sizeof(XtPointer),
- offset(sb.pageDecrementCBL), XtRCallback, NULL},
- { XmNtoTopCallback, XmCToTopCallback, XtRCallback, sizeof(XtPointer),
- offset(sb.toTopCBL), XtRCallback, NULL},
- { XmNtoBottomCallback, XmCToBottomCallback, XtRCallback, sizeof(XtPointer),
- offset(sb.toBottomCBL), XtRCallback, NULL},
- { XmNdragCallback, XmCDragCallback, XtRCallback, sizeof(XtPointer),
- offset(sb.dragCBL), XtRCallback, NULL},
-
- { XmNknobStyle, XmCKnobStyle, XtRString, sizeof(char *),
- offset(sb.knobStyle), XtRImmediate, NULL},
-
- { XmNarrowPosition, XmCArrowPosition, XtRString, sizeof(char *),
- offset(sb.arrowPosition), XtRImmediate, NULL},
- };
-
- /************************************************************************
- **
- ** Prototypes
- **
- */
-
- /*
- ** Actions
- */
- static void Select(Widget w, XEvent *event, String *parms, Cardinal *num_parms);
- static void Drag(Widget w, XEvent *event, String *parms, Cardinal *num_parms);
- static void Release(Widget w, XEvent *event, String *parms, Cardinal *num_parms);
- static void Jump(Widget w, XEvent *event, String *parms, Cardinal *num_parms);
- static void Abort(Widget w, XEvent *event, String *parms, Cardinal *num_parms);
-
- /*
- ** Methods
- */
- static void Initialize(Widget treq, Widget tnew, ArgList args, Cardinal *num_args);
- static Boolean SetValues(Widget current, Widget request, Widget nw, ArgList args, Cardinal *num_args);
- static void Destroy(Widget widget);
- static void Redisplay(Widget widget, XEvent *event, Region region);
- static void Resize(Widget widget);
- static void Realize(Widget widget, XtValueMask *valuemask, XSetWindowAttributes *attr);
-
- /*
- ** Private
- */
-
-
- /************************************************************************
- **
- ** Actions Table
- **
- */
- static XtActionsRec actions[] = {
- {"Select", Select},
- {"Drag", Drag},
- {"Release", Release},
- {"Jump", Jump},
- {"Abort", Abort},
- };
-
- /************************************************************************
- **
- ** Default Translation Table
- **
- */
- static char default_translations[] =
- "<Btn1Down>: Select()\n"
- "<Btn1Motion>: Drag()\n"
- "<Btn1Up>: Release()\n"
- "<Btn2Down>: Jump()\n"
- "<Btn2Motion>: Drag()\n"
- "<Btn2Up>: Release()\n"
- "<Key>Delete: Abort()"
- ;
-
- /************************************************************************
- **
- ** Class record initalization
- **
- */
- XlwScrollBarClassRec xlwScrollBarClassRec = {
- /* core_class fields */
- {
- /* superclass */ (WidgetClass) &coreClassRec,
- /* class_name */ "XlwScrollBar",
- /* widget_size */ sizeof(XlwScrollBarRec),
- /* class_initialize */ NULL,
- /* class_part_init */ NULL,
- /* class_inited */ False,
- /* initialize */ Initialize,
- /* initialize_hook */ NULL,
- /* realize */ Realize,
- /* actions */ actions,
- /* num_actions */ XtNumber(actions),
- /* resources */ resources,
- /* num_resources */ XtNumber(resources),
- /* xrm_class */ NULLQUARK,
- /* compress_motion */ True,
- /* compress_exposure */ XtExposeCompressMultiple,
- /* compress_enterleave */ True,
- /* visible_interest */ False,
- /* destroy */ Destroy,
- /* resize */ Resize,
- /* expose */ Redisplay,
- /* set_values */ SetValues,
- /* set_values_hook */ NULL,
- /* set_values_almost */ XtInheritSetValuesAlmost,
- /* get_values_hook */ NULL,
- /* accept_focus */ NULL,
- /* version */ XtVersionDontCheck,
- /* callback_private */ NULL,
- /* tm_table */ default_translations,
- /* query_geometry */ NULL,
- },
- /* scrollbar_class fields */
- {
- /* dummy_field */ 0,
- },
- };
-
- WidgetClass xlwScrollBarWidgetClass = (WidgetClass) &xlwScrollBarClassRec;
-
- /************************************************************************
- **
- ** Debug funcitons
- **
- */
-
- #ifdef SHOW_CLEAR
- static void myXClearArea(Display *dpy, Drawable d, int x, int y, int w, int h, Boolean exp, XlwScrollBarWidget widget)
- {
- XFillRectangle(dpy, d, widget->sb.topShadowGC, x, y, w, h);
- XSync(dpy, False);
- sleep(2);
- XClearArea(dpy, d, x, y, w, h, exp);
- }
-
- #define XClearArea(dpy,win,x,y,width,height,exp) myXClearArea(dpy,win,x,y,width,height,exp,w)
- #endif
-
- #ifdef CHECK_VALUES
- static void check(XlwScrollBarWidget w)
- {
- int height;
-
- height= widget_h(w);
- if( w->sb.showArrows ) height -= (2*arrow_h(w));
-
- if( (w->sb.above + w->sb.ss + w->sb.below > height) ||
- (w->sb.value < w->sb.minimum) ||
- (w->sb.value > w->sb.maximum - w->sb.sliderSize )
- )
- {
- printf("above=%d ss=%d below=%d height=%d\n",
- w->sb.above, w->sb.ss, w->sb.below, height);
- printf("value=%d min=%d max=%d ss=%d max-ss=%d\n",
- w->sb.value, w->sb.minimum, w->sb.maximum, w->sb.sliderSize, w->sb.maximum - w->sb.sliderSize);
- abort();
- }
- }
-
- # define CHECK(w) check(w)
- #else
- # define CHECK(w)
- #endif
-
- /************************************************************************
- **
- ** Static funcitons
- **
- */
-
- static void call_callbacks(XlwScrollBarWidget w, int reason, int value, int pixel,
- XEvent *event)
- {
- XlwScrollBarCallbackStruct cbs;
- Boolean called_anything;
-
- cbs.reason = reason;
- cbs.event = event;
- cbs.value = value;
- cbs.pixel = pixel;
-
- called_anything = False;
-
- switch( reason )
- {
- case XmCR_VALUE_CHANGED:
- XtCallCallbackList( (Widget)w, w->sb.valueChangedCBL, &cbs );
- called_anything = True;
- break;
- case XmCR_INCREMENT:
- if( w->sb.incrementCBL )
- {
- XtCallCallbackList( (Widget)w, w->sb.incrementCBL, &cbs );
- called_anything = True;
- }
- break;
- case XmCR_DECREMENT:
- if( w->sb.decrementCBL )
- {
- XtCallCallbackList( (Widget)w, w->sb.decrementCBL, &cbs );
- called_anything = True;
- }
- break;
- case XmCR_PAGE_INCREMENT:
- if( w->sb.incrementCBL )
- {
- XtCallCallbackList( (Widget)w, w->sb.pageIncrementCBL, &cbs );
- called_anything = True;
- }
- break;
- case XmCR_PAGE_DECREMENT:
- if( w->sb.decrementCBL )
- {
- XtCallCallbackList( (Widget)w, w->sb.pageDecrementCBL, &cbs );
- called_anything = True;
- }
- break;
- case XmCR_TO_TOP:
- if( w->sb.toTopCBL )
- {
- XtCallCallbackList( (Widget)w, w->sb.toTopCBL, &cbs );
- called_anything = True;
- }
- break;
- case XmCR_TO_BOTTOM:
- if( w->sb.toBottomCBL )
- {
- XtCallCallbackList( (Widget)w, w->sb.toBottomCBL, &cbs );
- called_anything = True;
- }
- break;
- case XmCR_DRAG:
- if( w->sb.dragCBL )
- {
- XtCallCallbackList( (Widget)w, w->sb.dragCBL, &cbs );
- }
- called_anything = True; /* Special Case */
- break;
- }
-
- if( !called_anything )
- {
- cbs.reason = XmCR_VALUE_CHANGED;
- XtCallCallbackList( (Widget)w, w->sb.valueChangedCBL, &cbs );
- }
- }
-
- /*
- ** Widget sizes minus the shadow and highlight area
- **
- */
- static int widget_x(XlwScrollBarWidget w)
- {
- return( w->sb.shadowThickness );
- }
-
- static int widget_y(XlwScrollBarWidget w)
- {
- return( w->sb.shadowThickness );
- }
-
- static int widget_w(XlwScrollBarWidget w)
- {
- int width, x = w->sb.shadowThickness;
-
- width = VERT(w) ? w->core.width : w->core.height;
-
- if( width <= (2 * x) )
- return( 1 );
- else
- return( width - (2 * x) );
- }
-
- static int widget_h(XlwScrollBarWidget w)
- {
- int height, y = w->sb.shadowThickness;
-
- height = VERT(w) ? w->core.height : w->core.width;
-
- if( height <= (2 * y) )
- return( 1 );
- else
- return( height - (2 * y) );
- }
-
- static int arrow_h(XlwScrollBarWidget w)
- {
- int width, height;
-
- width = widget_w(w);
- height= widget_h(w);
-
- if( width > ((height / 2) - (SS_MIN / 2) - 1) )
- {
- return( ((height / 2) - (SS_MIN / 2) - 1) );
- }
- else
- {
- return( width );
- }
- }
-
- static int event_x(XlwScrollBarWidget w, XEvent *event)
- {
- return( VERT(w) ? event->xbutton.x : event->xbutton.y );
- }
-
- static int event_y(XlwScrollBarWidget w, XEvent *event)
- {
- return( VERT(w) ? event->xbutton.y : event->xbutton.x );
- }
-
- /*
- ** Safe addition and subtraction
- */
- static int safe_add(int a, int b)
- {
- if( a > 0 && INT_MAX - a < b ) return( INT_MAX );
- else return( a + b );
- }
-
- static int safe_subtract(int a, int b)
- {
- if( a < 0 && -(INT_MIN - a) < b ) return( INT_MIN );
- else return( a - b );
- }
-
- static int knob_style(XlwScrollBarWidget w)
- {
- if( w->sb.knobStyle )
- {
- if( w->sb.knobStyle[0] == 'd' )
- {
- return( KNOB_DIMPLE );
- }
- }
- return( KNOB_PLAIN );
- }
-
- static Boolean arrow_same_end(XlwScrollBarWidget w)
- {
- if( w->sb.arrowPosition && w->sb.arrowPosition[0] == 's' )
- {
- return( True );
- }
- return( False );
- }
-
- /*
- ** GC and Pixel allocation
- */
- static GC get_gc(XlwScrollBarWidget w, Pixel fg, Pixel bg, Pixmap pm)
- {
- XGCValues values;
- XtGCMask mask;
-
- if (pm == w->sb.grayPixmap) {
- /* If we're using the gray pixmap, guarantee white on black ...
- * otherwise, we could end up with something odd like grey on white
- * when we're on a color display that ran out of color cells
- */
-
- fg = WhitePixelOfScreen(DefaultScreenOfDisplay(XtDisplay(w)));
- bg = BlackPixelOfScreen(DefaultScreenOfDisplay(XtDisplay(w)));
- }
-
- values.foreground = fg;
- values.background = bg;
- values.fill_style = FillOpaqueStippled;
- values.stipple = pm;
- mask = GCForeground | GCBackground |
- ( pm == None ? 0 : GCStipple | GCFillStyle );
- return( XtGetGC((Widget)w, mask, &values) );
- }
-
- static void make_shadow_pixels(XlwScrollBarWidget w)
- {
- Display *dpy = XtDisplay((Widget) w);
- Colormap cmap = w->core.colormap;
- XColor topc, botc;
- int top_frobbed, bottom_frobbed;
- Pixel bg, fg;
-
- top_frobbed = bottom_frobbed = 0;
-
- bg = w->core.background_pixel;
- fg = w->sb.foreground;
-
- if( w->sb.topShadowColor == (Pixel)~0) w->sb.topShadowColor = bg;
- if( w->sb.bottomShadowColor == (Pixel)~0) w->sb.bottomShadowColor = fg;
-
- if( w->sb.topShadowColor == bg || w->sb.topShadowColor == fg )
- {
- topc.pixel = bg;
- XQueryColor( dpy, cmap, &topc );
- /* don't overflow/wrap! */
- topc.red = MINL(65535, topc.red * 1.2);
- topc.green = MINL(65535, topc.green * 1.2);
- topc.blue = MINL(65535, topc.blue * 1.2);
- if( XAllocColor(dpy, cmap, &topc) )
- {
- if( topc.pixel == bg )
- {
- XFreeColors( dpy, cmap, &topc.pixel, 1, 0);
- topc.red = MINL(65535, topc.red + 0x8000);
- topc.green = MINL(65535, topc.green + 0x8000);
- topc.blue = MINL(65535, topc.blue + 0x8000);
- if( XAllocColor(dpy, cmap, &topc) )
- {
- w->sb.topShadowColor = topc.pixel;
- }
- }
- else
- {
- w->sb.topShadowColor = topc.pixel;
- }
-
- top_frobbed = 1;
- }
- }
-
- if( w->sb.bottomShadowColor == fg || w->sb.bottomShadowColor == bg )
- {
- botc.pixel = bg;
- XQueryColor( dpy, cmap, &botc );
- botc.red *= 0.6;
- botc.green *= 0.6;
- botc.blue *= 0.6;
- if( XAllocColor(dpy, cmap, &botc) )
- {
- if( botc.pixel == bg )
- {
- XFreeColors( dpy, cmap, &botc.pixel, 1, 0);
- botc.red = MINL(65535, botc.red + 0x4000);
- botc.green = MINL(65535, botc.green + 0x4000);
- botc.blue = MINL(65535, botc.blue + 0x4000);
- if( XAllocColor(dpy, cmap, &botc) )
- {
- w->sb.bottomShadowColor = botc.pixel;
- }
- }
- else
- {
- w->sb.bottomShadowColor = botc.pixel;
- }
- bottom_frobbed = 1;
- }
- }
-
- if( top_frobbed && bottom_frobbed )
- {
- int top_avg = ((topc.red / 3) + (topc.green / 3) + (topc.blue / 3));
- int bot_avg = ((botc.red / 3) + (botc.green / 3) + (botc.blue / 3));
- if( bot_avg > top_avg )
- {
- Pixel tmp = w->sb.topShadowColor;
- w->sb.topShadowColor = w->sb.bottomShadowColor;
- w->sb.bottomShadowColor = tmp;
- }
- else if( topc.pixel == botc.pixel )
- {
- if( botc.pixel == bg )
- w->sb.topShadowColor = bg;
- else
- w->sb.bottomShadowColor = fg;
- }
- }
-
- if (w->sb.topShadowColor == w->core.background_pixel ||
- w->sb.bottomShadowColor == w->core.background_pixel) {
-
- /* Assume we're in mono. This code should be okay even if we're
- * really in color but just short on color cells -- We want the
- * following behavior, which has been empirically determined to
- * work well for all fg/bg combinations in mono: If the trough
- * and thumb are BOTH black, then use a white top shadow and a
- * grey bottom shadow, otherwise use a grey top shadow and a
- * black bottom shadow.
- */
-
- Pixel white = WhitePixelOfScreen(DefaultScreenOfDisplay(XtDisplay(w)));
- Pixel black = BlackPixelOfScreen(DefaultScreenOfDisplay(XtDisplay(w)));
-
- /* Note: core.background_pixel is the color of the thumb ... */
-
- if (w->core.background_pixel == black &&
- w->sb.troughColor == black) {
-
- w->sb.topShadowColor = white;
- w->sb.bottomShadowPixmap = w->sb.grayPixmap;
-
- } else {
-
- w->sb.topShadowPixmap = w->sb.grayPixmap;
- w->sb.bottomShadowColor = black;
- }
-
- }
-
-
- }
-
- static void make_trough_pixel(XlwScrollBarWidget w)
- {
- Display *dpy = XtDisplay((Widget) w);
- Colormap cmap = DefaultColormapOfScreen( XtScreen((Widget)w) );
- XColor troughC;
-
- if( w->sb.troughColor == (Pixel)~0) w->sb.troughColor = w->core.background_pixel;
-
- if( w->sb.troughColor == w->core.background_pixel )
- {
- troughC.pixel = w->core.background_pixel;
- XQueryColor( dpy, cmap, &troughC );
- troughC.red *= 0.8;
- troughC.green *= 0.8;
- troughC.blue *= 0.8;
- if( XAllocColor(dpy, cmap, &troughC) )
- {
- w->sb.troughColor = troughC.pixel;
- }
- }
- }
-
- /*
- ** Draw 3d border
- */
- static void draw_shadows(Display *dpy, Drawable d,
- GC shine_gc, GC shadow_gc,
- int x, int y, int width, int height,
- int shadowT)
- {
- XSegment shine[10], shadow[10];
- int i;
-
- if(shadowT > (width / 2)) shadowT = (width / 2);
- if(shadowT > (height / 2)) shadowT = (height / 2);
- if(shadowT <= 0) return;
-
- for(i = 0; i < shadowT; i++)
- {
- /* Top segments */
- shine[i].x1 = x;
- shine[i].y2 = shine[i].y1 = y + i;
- shine[i].x2 = x + width - i - 1;
- /* Left segments */
- shine[i + shadowT].x2 = shine[i + shadowT].x1 = x + i;
- shine[i + shadowT].y1 = y + shadowT;
- shine[i + shadowT].y2 = y + height - i - 1;
-
- /* Bottom segments */
- shadow[i].x1 = x + i;
- shadow[i].y2 = shadow[i].y1 = y + height - i - 1;
- shadow[i].x2 = x + width - 1 ;
- /* Right segments */
- shadow[i + shadowT].x2 = shadow[i + shadowT].x1 = x + width - i - 1;
- shadow[i + shadowT].y1 = y + i + 1;
- shadow[i + shadowT].y2 = y + height - 1 ;
- }
-
- XDrawSegments( dpy, d, shine_gc, shine, shadowT * 2 );
- XDrawSegments( dpy, d, shadow_gc, shadow, shadowT * 2 );
- }
-
- /*
- ** Draw 3d arrows, left, up, down, and right
- */
- static int make_vert_seg(XSegment *seg, int x1, int y1, int x2, int y2, int shadowT)
- {
- int i;
-
- for(i=0; i<shadowT; i++)
- {
- seg[i].x1 = x1;
- seg[i].y1 = y1 + i;
- seg[i].x2 = x2;
- seg[i].y2 = y2 + i;
- }
- return( shadowT );
- }
-
- static int make_hor_seg(XSegment *seg, int x1, int y1, int x2, int y2, int shadowT)
- {
- int i;
-
- for(i=0; i<shadowT; i++)
- {
- seg[i].x1 = x1 + i;
- seg[i].y1 = y1;
- seg[i].x2 = x2 + i;
- seg[i].y2 = y2;
- }
- return( shadowT );
- }
-
- static void draw_arrow_up(Display *dpy, Drawable win, GC bgGC, GC shineGC, GC shadowGC,
- int x, int y, int width, int height, int shadowT)
- {
- XSegment shine[10], shadow[10];
- XPoint triangle[3];
- int mid;
-
- mid = width / 2;
-
- if(shadowT > (width / 2)) shadowT = (width / 2);
- if(shadowT > (height / 2)) shadowT = (height / 2);
- if(shadowT <= 0) shadowT = 0;
-
- /* / */
- make_vert_seg( shine,
- x, y + height - shadowT - 1,
- x + mid, y, shadowT );
- /* _\ */
- make_vert_seg( shadow,
- x, y + height - shadowT - 1,
- x + width - 1, y + height - shadowT - 1, shadowT );
- make_vert_seg( shadow + shadowT,
- x + mid, y,
- x + width - 1, y + height - shadowT - 1, shadowT );
-
- triangle[0].x = x;
- triangle[0].y = y + height - 1;
- triangle[1].x = x + mid;
- triangle[1].y = y;
- triangle[2].x = x + width - 1;
- triangle[2].y = y + height - 1;
-
- XFillPolygon( dpy, win, bgGC, triangle, 3, Convex, ArcChord );
-
- XDrawSegments( dpy, win, shadowGC, shadow, shadowT * 2 );
- XDrawSegments( dpy, win, shineGC, shine, shadowT );
- }
-
- static void draw_arrow_left(Display *dpy, Drawable win, GC bgGC, GC shineGC, GC shadowGC,
- int x, int y, int width, int height, int shadowT)
- {
- XSegment shine[10], shadow[10];
- XPoint triangle[3];
- int mid;
-
- mid = width / 2;
-
- if(shadowT > (width / 2)) shadowT = (width / 2);
- if(shadowT > (height / 2)) shadowT = (height / 2);
- if(shadowT <= 0) shadowT = 0;
-
- /* / */
- make_hor_seg( shine,
- x, y + mid,
- x + width - shadowT - 1, y, shadowT );
- /* \| */
- make_hor_seg( shadow,
- x, y + mid,
- x + width - shadowT - 1, y + height - 1, shadowT );
- make_hor_seg( shadow + shadowT,
- x + width - shadowT - 1, y,
- x + width - shadowT - 1, y + height - 1, shadowT );
-
- triangle[0].x = x + width - 1;
- triangle[0].y = y + height - 1;
- triangle[1].x = x;
- triangle[1].y = y + mid;
- triangle[2].x = x + width - 1;
- triangle[2].y = y;
-
- XFillPolygon( dpy, win, bgGC, triangle, 3, Convex, ArcChord );
-
- XDrawSegments( dpy, win, shadowGC, shadow, shadowT * 2 );
- XDrawSegments( dpy, win, shineGC, shine, shadowT );
- }
-
- static void draw_arrow_down(Display *dpy, Drawable win, GC bgGC, GC shineGC, GC shadowGC,
- int x, int y, int width, int height, int shadowT)
- {
- XSegment shine[10], shadow[10];
- XPoint triangle[3];
- int mid;
-
- mid = width / 2;
-
- if(shadowT > (width / 2)) shadowT = (width / 2);
- if(shadowT > (height / 2)) shadowT = (height / 2);
- if(shadowT <= 0) shadowT = 0;
-
- /* \- */
- make_vert_seg( shine,
- x, y,
- x + mid, y + height - shadowT - 1, shadowT );
- make_vert_seg( shine + shadowT,
- x, y,
- x + width - 1, y, shadowT );
- /* / */
- make_vert_seg( shadow,
- x + width - 1, y,
- x + mid, y + height - shadowT - 1, shadowT );
-
- triangle[0].x = x;
- triangle[0].y = y;
- triangle[1].x = x + mid;
- triangle[1].y = y + height - 1;
- triangle[2].x = x + width - 1;
- triangle[2].y = y;
-
- XFillPolygon( dpy, win, bgGC, triangle, 3, Convex, ArcChord );
-
- XDrawSegments( dpy, win, shadowGC, shadow, shadowT );
- XDrawSegments( dpy, win, shineGC, shine, shadowT * 2 );
- }
-
- static void draw_arrow_right(Display *dpy, Drawable win, GC bgGC, GC shineGC, GC shadowGC,
- int x, int y, int width, int height, int shadowT)
- {
- XSegment shine[10], shadow[10];
- XPoint triangle[3];
- int mid;
-
- mid = width / 2;
-
- if(shadowT > (width / 2)) shadowT = (width / 2);
- if(shadowT > (height / 2)) shadowT = (height / 2);
- if(shadowT <= 0) shadowT = 0;
-
- /* |\ */
- make_hor_seg( shine,
- x, y,
- x + width - shadowT - 1, y + mid, shadowT );
- make_hor_seg( shine + shadowT,
- x, y,
- x, y + height -1, shadowT );
- /* / */
- make_hor_seg( shadow,
- x, y + height -1,
- x + width - shadowT - 1, y + mid, shadowT );
-
- triangle[0].x = x + 1;
- triangle[0].y = y + height - 1;
- triangle[1].x = x + width - 1;
- triangle[1].y = y + mid;
- triangle[2].x = x + 1;
- triangle[2].y = y;
-
- XFillPolygon( dpy, win, bgGC, triangle, 3, Convex, ArcChord );
-
- XDrawSegments( dpy, win, shadowGC, shadow, shadowT );
- XDrawSegments( dpy, win, shineGC, shine, shadowT * 2 );
- }
-
- static void draw_dimple(Display *dpy, Drawable win, GC shine, GC shadow,
- int x, int y, int width, int height)
- {
- XDrawArc(dpy, win, shine, x, y, width, height, 46*64, 180*64);
- XDrawArc(dpy, win, shadow, x, y, width, height, 45*64, -179*64);
- }
-
- /*
- ** Scrollbar values -> pixels, pixels -> scrollbar values
- */
-
- static void seg_pixel_sizes(XlwScrollBarWidget w, int *above_return, int *ss_return,
- int *below_return)
- {
- float total, height, fuz;
- int value;
- int above, ss, below;
-
- height= widget_h(w);
- if( w->sb.showArrows ) height -= (2*arrow_h(w));
-
- value = w->sb.value - w->sb.minimum;
-
- total = w->sb.maximum - w->sb.minimum;
- fuz = total / 2;
-
- ss = ((height * w->sb.sliderSize + fuz) / total);
- above = ((height * value + fuz) / total);
- below = ((height) - (ss + above));
-
- /* Dont' let knob get smaller than SS_MIN */
- if( ss < SS_MIN )
- {
- /* add a percent amount for interger rounding */
- float tmp = ((((float)(SS_MIN - ss) * (float)value)) / total) + 0.5;
-
- above -= (int)tmp;
- ss = SS_MIN;
- below = ((height) - (ss + above));
-
- if( above < 0 )
- {
- above = 0;
- below = height - ss;
- }
- if( below < 0 )
- {
- above = height - ss;
- below = 0;
- }
- if( ss > height )
- {
- above = 0;
- ss = height;
- below = 0;
- }
- }
-
- *above_return = above;
- *ss_return = ss;
- *below_return = below;
-
- CHECK(w);
- }
-
- static void verify_values(XlwScrollBarWidget w)
- {
- int total = w->sb.maximum - w->sb.minimum;
-
- if( w->sb.sliderSize > total )
- {
- w->sb.sliderSize = total;
- }
- if( w->sb.pageIncrement > total )
- {
- w->sb.pageIncrement = total;
- }
- if( w->sb.increment > total )
- {
- w->sb.increment = total;
- }
- if( w->sb.value < w->sb.minimum )
- {
- w->sb.value = w->sb.minimum;
- }
- if( w->sb.value > w->sb.maximum - w->sb.sliderSize)
- {
- w->sb.value = w->sb.maximum - w->sb.sliderSize;
- }
- }
-
- static int value_from_pixel(XlwScrollBarWidget w, int above)
- {
- float total, height, fuz;
- int value, ss;
-
- height= widget_h(w);
- if( w->sb.showArrows ) height -= (2*arrow_h(w));
-
- total = w->sb.maximum - w->sb.minimum;
- fuz = height / 2;
-
- ss = ((height * w->sb.sliderSize + (total / 2)) / total);
-
- if( ss < SS_MIN )
- {
- /* add a percent amount for interger rounding */
- above += ((((SS_MIN - ss) * above) + fuz) / height);
- }
-
- {
- /* Prevent SIGFPE's that would occur if we don't truncate the
- value. */
- float floatval = w->sb.minimum + ((float)(above * total + fuz ) / height);
- if (floatval >= (float) INT_MAX)
- value = INT_MAX;
- else if (floatval <= (float) INT_MIN)
- value = INT_MIN;
- else
- value = floatval;
- }
-
- return( value );
- }
-
-
- static void redraw_dimple(XlwScrollBarWidget w, Display *dpy, Window win,
- int x, int y, int width, int height)
- {
- GC shine, shadow;
- int shadowT, size;
-
- if( KNOB_DIMPLE == knob_style(w) )
- {
- if( w->sb.armed == ARM_KNOB )
- {
- shine = w->sb.bottomShadowGC;
- shadow = w->sb.topShadowGC;
- }
- else
- {
- shine = w->sb.topShadowGC;
- shadow = w->sb.bottomShadowGC;
- }
-
- shadowT = w->sb.shadowThickness;
-
- x += shadowT;
- y += shadowT;
- width -= 2*shadowT;
- height -= 2*shadowT;
-
- size = (width < height ? width : height) * 3 / 4;
-
- if( size%2 != (width < height ? width : height)%2 ) size--;
-
- DBUG (fprintf(stderr, "%d %d\n",
- x + (width / 2) - (size / 2) - 2*shadowT,
- width - size - shadowT));
-
- draw_dimple( dpy, win, shine, shadow,
- x + (width / 2) - (size / 2),
- y + (height / 2) - (size / 2),
- size, size );
- }
- }
-
- static void draw_knob(XlwScrollBarWidget w, int above, int ss, int below)
- {
- Display *dpy = XtDisplay((Widget)w);
- Window win = XtWindow((Widget)w);
- int x, y, width, height;
- int shadowT;
-
- x = widget_x(w);
- y = widget_y(w);
- width = widget_w(w);
- height = widget_h(w);
-
- shadowT = w->sb.shadowThickness;
-
- if(shadowT > (width / 2)) shadowT = (width / 2);
- if(shadowT > (height / 2)) shadowT = (height / 2);
- if(shadowT <= 0) return;
-
- if( w->sb.showArrows && !arrow_same_end(w) ) y += (arrow_h(w));
-
- /* trough above knob */
- if( above > 0 )
- {
- if( VERT(w) )
- XClearArea( dpy, win, x, y, width, above, False );
- else
- XClearArea( dpy, win, y, x, above, width, False );
- }
-
- /* knob */
- if( VERT(w) )
- {
- draw_shadows( dpy, win, w->sb.topShadowGC, w->sb.bottomShadowGC,
- x, y + above, width, ss, shadowT);
- XFillRectangle( dpy, win,
- w->sb.backgroundGC,
- x+shadowT, y + above + shadowT, width-2*shadowT, ss-2*shadowT );
- redraw_dimple(w, dpy, win, x, y + above, width, ss);
- }
- else
- {
- draw_shadows( dpy, win, w->sb.topShadowGC, w->sb.bottomShadowGC,
- y + above, x, ss, width, shadowT);
- XFillRectangle( dpy, win,
- w->sb.backgroundGC,
- y + above + shadowT, x+shadowT, ss-2*shadowT, width-2*shadowT );
- redraw_dimple(w, dpy, win, y + above, x, ss, width);
- }
-
- /* trough below knob */
- if( below > 0 )
- {
- if( VERT(w) )
- XClearArea( dpy, win, x, y + above + ss, width, below, False );
- else
- XClearArea( dpy, win, y + above + ss, x, below, width, False );
- }
-
- CHECK(w);
- }
-
- static void redraw_up_arrow(XlwScrollBarWidget w, Boolean armed, Boolean clear_behind)
- {
- Display *dpy = XtDisplay((Widget)w);
- Window win = XtWindow((Widget)w);
- GC bg, shine, shadow;
- int x, y, width, height, arrow_height, shadowT;
-
- x = widget_x(w);
- y = widget_y(w);
- width = widget_w(w);
- height = widget_h(w);
- arrow_height = arrow_h(w);
-
- shadowT = w->sb.shadowThickness;
- bg = w->sb.backgroundGC;
-
- if( armed )
- {
- shine = w->sb.bottomShadowGC;
- shadow = w->sb.topShadowGC;
- }
- else
- {
- shine = w->sb.topShadowGC;
- shadow = w->sb.bottomShadowGC;
- }
-
- if( VERT(w) )
- {
- if( arrow_same_end(w) )
- {
- y += height - 2*arrow_h(w) + 2;
- }
- if( clear_behind )
- XClearArea( dpy, win, x, y, width, arrow_height + 1, False );
- draw_arrow_up( dpy, win, bg, shine, shadow,
- x + (width - arrow_height)/2, y,
- arrow_height, arrow_height, shadowT );
- }
- else
- {
- if( arrow_same_end(w) )
- {
- y += height - 2*arrow_h(w);
- }
- if( clear_behind )
- XClearArea( dpy, win, y, x, arrow_height + 1, height, False );
- draw_arrow_left( dpy, win, bg, shine, shadow,
- y, x + (width - arrow_height)/2,
- arrow_height, arrow_height, shadowT );
- }
- }
-
- static void redraw_down_arrow(XlwScrollBarWidget w, Boolean armed, Boolean clear_behind)
- {
- Display *dpy = XtDisplay((Widget)w);
- Window win = XtWindow((Widget)w);
- GC bg, shine, shadow;
- int x, y, width, height, arrow_height, shadowT;
-
- x = widget_x(w);
- y = widget_y(w);
- width = widget_w(w);
- height = widget_h(w);
- arrow_height = arrow_h(w);
-
- shadowT = w->sb.shadowThickness;
- bg = w->sb.backgroundGC;
-
- if( armed )
- {
- shine = w->sb.bottomShadowGC;
- shadow = w->sb.topShadowGC;
- }
- else
- {
- shine = w->sb.topShadowGC;
- shadow = w->sb.bottomShadowGC;
- }
-
- if( VERT(w) )
- {
- if( clear_behind )
- XClearArea( dpy, win, x, y + height - arrow_height, width, arrow_height + 1, False );
- draw_arrow_down( dpy, win, bg, shine, shadow,
- x + (width - arrow_height)/2, y + height - arrow_height + 1,
- arrow_height, arrow_height, shadowT );
- }
- else
- {
- if( clear_behind )
- XClearArea( dpy, win, y + height - arrow_height, x, arrow_height + 1, height, False );
- draw_arrow_right( dpy, win, bg, shine, shadow,
- y + height - arrow_height + 1, x + (width - arrow_height)/2,
- arrow_height, arrow_height, shadowT );
- }
- }
-
- static void redraw_everything(XlwScrollBarWidget w, Region region, Boolean behind_arrows)
- {
- Display *dpy = XtDisplay((Widget)w);
- Window win = XtWindow((Widget)w);
- int x, y, width, height, shadowT, tmp;
-
- x = widget_x(w);
- y = widget_y(w);
- width = widget_w(w);
- height = widget_h(w);
- shadowT = w->sb.shadowThickness;
-
- if( w->sb.showArrows )
- {
- if( region == NULL || XRectInRegion( region, x, y, width, width ) )
- {
- redraw_up_arrow( w, False, behind_arrows );
- }
- if( VERT(w) )
- {
- y = y + height - width + 1;
- }
- else
- {
- tmp = y;
- y = x;
- x = tmp + height - width + 1;
- }
- if( region == NULL || XRectInRegion( region, x, y, width, width ) )
- {
- redraw_down_arrow( w, False, behind_arrows );
- }
- }
-
- draw_shadows( dpy, win, w->sb.bottomShadowGC, w->sb.topShadowGC,
- 0, 0, w->core.width, w->core.height, shadowT);
-
- draw_knob( w, w->sb.above, w->sb.ss, w->sb.below );
-
- }
-
- /************************************************************************
- **
- ** Method funcitons
- **
- */
-
- /*
- ** Initialize
- */
- static void Initialize(Widget treq, Widget tnew, ArgList args, Cardinal *num_args)
- {
- XlwScrollBarWidget request = (XlwScrollBarWidget) treq;
- XlwScrollBarWidget w = (XlwScrollBarWidget) tnew;
- Display *dpy = XtDisplay((Widget)w);
- Window win = RootWindowOfScreen( DefaultScreenOfDisplay(dpy) );
-
- DBUG(fprintf(stderr, "Initialize\n"));
-
- if( request->core.width == 0 ) w->core.width += (VERT(w) ? 12 : 25);
- if( request->core.height == 0 ) w->core.height += (VERT(w) ? 25 : 12);
-
- verify_values(w);
-
- w->sb.lastY = 0;
- w->sb.above = 0;
- w->sb.ss = 0;
- w->sb.below = 0;
- w->sb.armed = ARM_NONE;
-
- if( w->sb.shadowThickness > 5 ) w->sb.shadowThickness = 5;
-
- w->sb.grayPixmap =
- XCreatePixmapFromBitmapData( dpy, win, (char *) gray_bits, gray_width,
- gray_height, 1, 0, 1);
-
- make_trough_pixel( w );
-
- make_shadow_pixels( w );
-
- w->sb.backgroundGC = get_gc(w, w->core.background_pixel, w->core.background_pixel, None);
- w->sb.topShadowGC = get_gc(w, w->sb.topShadowColor, w->core.background_pixel, w->sb.topShadowPixmap);
- w->sb.bottomShadowGC = get_gc(w, w->sb.bottomShadowColor, w->core.background_pixel, w->sb.bottomShadowPixmap);
-
- w->sb.fullRedrawNext = True;
- }
-
- /*
- ** Destroy
- */
- static void Destroy(Widget widget)
- {
- XlwScrollBarWidget w = (XlwScrollBarWidget) widget;
- Display *dpy = XtDisplay((Widget)w);
-
- DBUG(fprintf(stderr, "Destroy\n"));
-
- XtReleaseGC(widget, w->sb.bottomShadowGC);
- XtReleaseGC(widget, w->sb.topShadowGC);
- XtReleaseGC(widget, w->sb.backgroundGC);
-
- XFreePixmap( dpy, w->sb.grayPixmap );
- }
-
- /*
- ** Realize
- */
- static void Realize(Widget widget, XtValueMask *valuemask, XSetWindowAttributes *attr)
- {
- XlwScrollBarWidget w = (XlwScrollBarWidget) widget;
- Display *dpy = XtDisplay((Widget)w);
- Window win;
- XSetWindowAttributes win_attr;
-
- DBUG(fprintf(stderr, "Realize\n"));
-
- (*coreClassRec.core_class.realize)(widget, valuemask, attr);
-
- win = XtWindow((Widget)w);
-
- seg_pixel_sizes(w, &w->sb.above, &w->sb.ss, &w->sb.below);
-
- XSetWindowBackground( dpy, win, w->sb.troughColor);
-
- /* Change bit gravity so widget is not cleared on resize */
- win_attr.bit_gravity = NorthWestGravity;
- XChangeWindowAttributes( dpy, win, CWBitGravity , &win_attr);
-
- }
-
- /*
- ** Resize
- */
- static void Resize(Widget widget)
- {
- XlwScrollBarWidget w = (XlwScrollBarWidget) widget;
- Display *dpy = XtDisplay((Widget)w);
- Window win = XtWindow((Widget)w);
-
- if( XtIsRealized(widget) )
- {
- DBUG(fprintf(stderr, "Resize = %08lx\n", w));
-
- seg_pixel_sizes(w, &w->sb.above, &w->sb.ss, &w->sb.below);
-
- /*redraw_everything(w, NULL, True);*/
-
- w->sb.fullRedrawNext = True;
- /* Force expose event */
- XClearArea(dpy, win, widget_x(w), widget_y(w), 1, 1, True);
- }
- }
-
- /*
- ** Redisplay
- */
- static void Redisplay(Widget widget, XEvent *event, Region region)
- {
- XlwScrollBarWidget w = (XlwScrollBarWidget) widget;
-
- DBUG(fprintf(stderr, "Redisplay = %08lx\n", w));
-
- if( XtIsRealized(widget) )
- {
- if( w->sb.fullRedrawNext )
- {
- redraw_everything(w, NULL, True);
- }
- else
- {
- redraw_everything(w, region, False);
- }
- w->sb.fullRedrawNext = False;
- }
- }
-
- /*
- ** SetValues
- */
- static Boolean SetValues(Widget current, Widget request, Widget neww, ArgList args, Cardinal *num_args)
- {
- XlwScrollBarWidget cur = (XlwScrollBarWidget) current;
- XlwScrollBarWidget w = (XlwScrollBarWidget) neww;
- Boolean do_redisplay = False;
-
- if( cur->sb.troughColor != w->sb.troughColor )
- {
- if( XtIsRealized((Widget)w) )
- {
- XSetWindowBackground( XtDisplay((Widget)w), XtWindow((Widget)w),
- w->sb.troughColor);
- do_redisplay = True;
- }
- }
-
- if( cur->core.background_pixel != w->core.background_pixel )
- {
- XtReleaseGC((Widget)cur, cur->sb.backgroundGC);
- w->sb.backgroundGC = get_gc(w, w->core.background_pixel, w->core.background_pixel, None);
- do_redisplay = True;
- }
-
- if( cur->sb.topShadowColor != w->sb.topShadowColor ||
- cur->sb.topShadowPixmap != w->sb.topShadowPixmap )
- {
- XtReleaseGC((Widget)cur, cur->sb.topShadowGC);
- w->sb.topShadowGC = get_gc(w, w->sb.topShadowColor, w->core.background_pixel, w->sb.topShadowPixmap);
- do_redisplay = True;
- }
-
- if( cur->sb.bottomShadowColor != w->sb.bottomShadowColor ||
- cur->sb.bottomShadowPixmap != w->sb.bottomShadowPixmap )
- {
- XtReleaseGC((Widget)cur, cur->sb.bottomShadowGC);
- w->sb.bottomShadowGC = get_gc(w, w->sb.bottomShadowColor, w->core.background_pixel, w->sb.bottomShadowPixmap);
- do_redisplay = True;
- }
-
- if( cur->sb.orientation != w->sb.orientation )
- {
- do_redisplay = True;
- }
-
-
- if( cur->sb.minimum != w->sb.minimum ||
- cur->sb.maximum != w->sb.maximum ||
- cur->sb.sliderSize != w->sb.sliderSize ||
- cur->sb.value != w->sb.value ||
- cur->sb.pageIncrement != w->sb.pageIncrement ||
- cur->sb.increment != w->sb.increment )
- {
- verify_values(w);
- if( XtIsRealized((Widget)w) )
- {
- seg_pixel_sizes(w, &w->sb.above, &w->sb.ss, &w->sb.below);
- draw_knob( w, w->sb.above, w->sb.ss, w->sb.below );
- }
- }
-
- if( w->sb.shadowThickness > 5 ) w->sb.shadowThickness = 5;
-
- return( do_redisplay );
- }
-
- void XlwScrollBarGetValues(Widget widget, int *value, int *sliderSize,
- int *increment, int *pageIncrement)
- {
- XlwScrollBarWidget w = (XlwScrollBarWidget)widget;
-
- if( w && XtClass((Widget)w) == xlwScrollBarWidgetClass )
- {
- if( value ) *value = w->sb.value;
- if( sliderSize ) *sliderSize = w->sb.sliderSize;
- if( increment ) *increment = w->sb.increment;
- if( pageIncrement ) *pageIncrement = w->sb.pageIncrement;
- }
- }
-
- void XlwScrollBarSetValues(Widget widget, int value, int sliderSize,
- int increment, int pageIncrement, Boolean notify)
- {
- XlwScrollBarWidget w = (XlwScrollBarWidget)widget;
- int last_value;
-
- if( w && XtClass((Widget)w) == xlwScrollBarWidgetClass &&
- (w->sb.value != value ||
- w->sb.sliderSize != sliderSize ||
- w->sb.increment != increment ||
- w->sb.pageIncrement != pageIncrement ))
- {
- w->sb.value = value;
- w->sb.sliderSize = sliderSize;
- w->sb.increment = increment;
- w->sb.pageIncrement = pageIncrement;
-
- verify_values(w);
-
- if( XtIsRealized(widget) )
- {
- seg_pixel_sizes(w, &w->sb.above, &w->sb.ss, &w->sb.below);
- draw_knob(w, w->sb.above, w->sb.ss, w->sb.below);
-
- last_value = w->sb.value;
- w->sb.value = value_from_pixel(w, w->sb.above);
- verify_values(w);
-
- if( w->sb.value != last_value && notify )
- {
- call_callbacks( w, XmCR_VALUE_CHANGED, w->sb.value, 0, NULL );
- }
- }
- }
- }
-
- /************************************************************************
- **
- ** Action funcitons
- **
- */
-
- static void timer(XtPointer data, XtIntervalId *id)
- {
- XlwScrollBarWidget w = (XlwScrollBarWidget)data;
- int reason, last_value;
-
- if( w->sb.armed != ARM_NONE )
- {
- last_value = w->sb.value;
- reason = XmCR_NONE;
-
- switch( w->sb.armed )
- {
- case ARM_PAGEUP:
- w->sb.value = safe_subtract( w->sb.value, w->sb.pageIncrement );
- reason = XmCR_PAGE_DECREMENT;
- break;
- case ARM_PAGEDOWN:
- w->sb.value = safe_add( w->sb.value, w->sb.pageIncrement );
- reason = XmCR_PAGE_INCREMENT;
- break;
- case ARM_UP:
- w->sb.value = safe_subtract( w->sb.value, w->sb.increment );
- reason = XmCR_DECREMENT;
- break;
- case ARM_DOWN:
- w->sb.value = safe_add( w->sb.value, w->sb.increment );
- reason = XmCR_INCREMENT;
- break;
- }
-
- verify_values(w);
-
- if( last_value != w->sb.value )
- {
- seg_pixel_sizes(w, &w->sb.above, &w->sb.ss, &w->sb.below);
- draw_knob(w, w->sb.above, w->sb.ss, w->sb.below);
-
- call_callbacks( w, reason, w->sb.value, 0, NULL );
-
- XtAppAddTimeOut( XtWidgetToApplicationContext((Widget)w),
- (unsigned long) w->sb.repeatDelay,
- timer, (XtPointer) w );
- }
- }
- }
-
- static int what_button(XlwScrollBarWidget w, int mouse_x, int mouse_y)
- {
- int x, y, width, height, arrow_height_top, arrow_height_bottom;
- int where;
-
- x = widget_x(w);
- y = widget_y(w);
- width = widget_w(w);
- height = widget_h(w);
-
- #if 0
- arrow_height = w->sb.showArrows ? arrow_h(w) : 0;
- #endif
- if( w->sb.showArrows )
- {
- if( arrow_same_end(w) )
- {
- arrow_height_top = 0;
- arrow_height_bottom = 2*arrow_h(w);
- }
- else
- {
- arrow_height_top = arrow_height_bottom = arrow_h(w);
- }
- }
- else
- {
- arrow_height_top = arrow_height_bottom = 0;
- }
-
- where = BUTTON_NONE;
-
- if( mouse_x > x && mouse_x < (x + width) )
- {
- if( mouse_y > (y + arrow_height_top) && mouse_y < (y + height - arrow_height_bottom) )
- {
- if( mouse_y < (y + w->sb.above + arrow_height_top) )
- {
- where = BUTTON_TROUGH_ABOVE;
- }
- else if( mouse_y > (y + w->sb.above + w->sb.ss + arrow_height_top) )
- {
- where = BUTTON_TROUGH_BELOW;
- }
- else
- {
- where = BUTTON_KNOB;
- }
- }
- else if( arrow_same_end(w) )
- {
- if( mouse_y > (y + height - arrow_height_bottom + 1) && mouse_y < (y + height) )
- {
- if( mouse_y < (y + height - arrow_height_bottom/2) )
- {
- where = BUTTON_UP_ARROW;
- }
- else
- {
- where = BUTTON_DOWN_ARROW;
- }
- }
- }
- else
- {
- if( mouse_y > y && mouse_y < (y + arrow_height_top) )
- {
- where = BUTTON_UP_ARROW;
- }
- else if( mouse_y > (y + height - arrow_height_bottom + 1) && mouse_y < (y + height) )
- {
- where = BUTTON_DOWN_ARROW;
- }
- }
- }
- #if 0
- if( mouse_x > x && mouse_x < (x + width) )
- {
- if( mouse_y > (y + arrow_height) && mouse_y < (y + height - arrow_height) )
- {
- if( mouse_y < (y+w->sb.above+arrow_height) )
- {
- where = BUTTON_TROUGH_ABOVE;
- }
- else if( mouse_y > (y + w->sb.above + w->sb.ss + arrow_height) )
- {
- where = BUTTON_TROUGH_BELOW;
- }
- else
- {
- where = BUTTON_KNOB;
- }
- }
- else if( mouse_y > y && mouse_y < (y + arrow_height) )
- {
- where = BUTTON_UP_ARROW;
- }
- else if( mouse_y > (y + height - arrow_height + 1) && mouse_y < (y + height) )
- {
- where = BUTTON_DOWN_ARROW;
- }
- }
- #endif
- return( where );
- }
-
- /*
- ** Select
- */
- static void Select(Widget widget, XEvent *event, String *parms, Cardinal *num_parms)
- {
- XlwScrollBarWidget w = (XlwScrollBarWidget)widget;
- int mouse_x, mouse_y;
- int reason, last_value;
-
- DBUG(fprintf(stderr, "Select:\n"));
-
- mouse_x = event_x( w, event );
- mouse_y = event_y( w, event );
-
- w->sb.savedValue = w->sb.value;
-
- last_value = w->sb.value;
- reason = XmCR_NONE;
-
- XtGrabKeyboard( (Widget)w, False, GrabModeAsync, GrabModeAsync, event->xbutton.time );
-
- switch( what_button(w, mouse_x, mouse_y) )
- {
- case BUTTON_TROUGH_ABOVE:
- w->sb.value = safe_subtract( w->sb.value, w->sb.pageIncrement );
- w->sb.armed = ARM_PAGEUP;
- reason = XmCR_PAGE_DECREMENT;
- break;
- case BUTTON_TROUGH_BELOW:
- w->sb.value = safe_add( w->sb.value, w->sb.pageIncrement );
- w->sb.armed = ARM_PAGEDOWN;
- reason = XmCR_PAGE_INCREMENT;
- break;
- case BUTTON_KNOB:
- w->sb.lastY = mouse_y;
- w->sb.armed = ARM_KNOB;
- draw_knob(w, w->sb.above, w->sb.ss, w->sb.below);
- break;
- case BUTTON_UP_ARROW:
- if( event->xbutton.state & ControlMask )
- {
- w->sb.value = INT_MIN;
- w->sb.armed = ARM_UP;
- reason = XmCR_TO_TOP;
- }
- else
- {
- w->sb.value = safe_subtract( w->sb.value, w->sb.increment );
- w->sb.armed = ARM_UP;
- reason = XmCR_DECREMENT;
- }
- redraw_up_arrow(w, True, False);
- break;
- case BUTTON_DOWN_ARROW:
- if( event->xbutton.state & ControlMask )
- {
- w->sb.value = INT_MAX;
- w->sb.armed = ARM_DOWN;
- reason = XmCR_TO_BOTTOM;
- }
- else
- {
- w->sb.value = safe_add( w->sb.value, w->sb.increment );
- w->sb.armed = ARM_DOWN;
- reason = XmCR_INCREMENT;
- }
- redraw_down_arrow(w, True, False);
- break;
- }
-
- verify_values(w);
-
- if( last_value != w->sb.value )
- {
- seg_pixel_sizes(w, &w->sb.above, &w->sb.ss, &w->sb.below);
- draw_knob(w, w->sb.above, w->sb.ss, w->sb.below);
-
- call_callbacks( w, reason, w->sb.value, mouse_y, event );
-
- XtAppAddTimeOut( XtWidgetToApplicationContext((Widget)w),
- (unsigned long) w->sb.initialDelay,
- timer, (XtPointer) w );
- }
-
- CHECK(w);
- }
-
- /*
- ** Drag
- */
- static void Drag(Widget widget, XEvent *event, String *parms, Cardinal *num_parms)
- {
- XlwScrollBarWidget w = (XlwScrollBarWidget)widget;
- int diff;
- int height, mouse_y;
- int last_value, last_above;
-
- DBUG(fprintf(stderr, "Drag:\n"));
-
- if( w->sb.armed == ARM_KNOB )
- {
- height = widget_h(w);
- if( w->sb.showArrows ) height -= (2*arrow_h(w));
-
- mouse_y = event_y( w, event );
-
- diff = mouse_y - w->sb.lastY;
-
- last_above = w->sb.above;
- last_value = w->sb.value;
-
- if( diff < 0 )
- {
- /* up */
- w->sb.above -= (-diff);
- if( w->sb.above < 0 )
- {
- mouse_y = (mouse_y - w->sb.above);
- w->sb.above = 0;
- diff = 0;
- w->sb.below = height - w->sb.ss;
- }
- w->sb.below -= diff;
- CHECK(w);
- }
- else if( diff > 0 )
- {
- /* down */
- w->sb.above += diff;
- if( w->sb.above + w->sb.ss > height )
- {
- mouse_y = height + (mouse_y - (w->sb.above + w->sb.ss));
- w->sb.above = height - w->sb.ss;
- diff = 0;
- w->sb.below = 0;
- }
- w->sb.below -= diff;
- CHECK(w);
- }
-
- if( last_above != w->sb.above )
- {
- draw_knob(w, w->sb.above, w->sb.ss, w->sb.below);
-
- w->sb.lastY = mouse_y;
-
- w->sb.value = value_from_pixel(w, w->sb.above);
- verify_values(w);
- CHECK(w);
-
- if( w->sb.value != last_value )
- {
- call_callbacks( w, XmCR_DRAG, w->sb.value, event_y(w, event), event );
- }
- }
- }
- CHECK(w);
- }
-
- /*
- ** Release
- */
- static void Release(Widget widget, XEvent *event, String *parms, Cardinal *num_parms)
- {
- XlwScrollBarWidget w = (XlwScrollBarWidget)widget;
-
- DBUG(fprintf(stderr, "EndDrag:\n"));
-
- switch( w->sb.armed )
- {
- case ARM_KNOB:
- call_callbacks( w, XmCR_VALUE_CHANGED, w->sb.value, event_y(w, event), event );
- w->sb.armed = ARM_NONE;
- draw_knob(w, w->sb.above, w->sb.ss, w->sb.below);
- break;
- case ARM_UP:
- redraw_up_arrow(w, False, False);
- break;
- case ARM_DOWN:
- redraw_down_arrow(w, False, False);
- break;
- }
-
- XtUngrabKeyboard( (Widget)w, event->xbutton.time );
-
- w->sb.armed = ARM_NONE;
- }
-
- /*
- ** Jump
- */
- static void Jump(Widget widget, XEvent *event, String *parms, Cardinal *num_parms)
- {
- XlwScrollBarWidget w = (XlwScrollBarWidget)widget;
- int x, y, width, height, mouse_x, mouse_y;
- int arrow_height;
- int last_above, last_value;
-
- DBUG(fprintf(stderr, "Jump:\n"));
-
- x = widget_x(w);
- y = widget_y(w);
- width = widget_w(w);
- height = widget_h(w);
- mouse_x = event_x( w, event );
- mouse_y = event_y( w, event );
-
- arrow_height = w->sb.showArrows ? arrow_h(w) : 0;
-
- XtGrabKeyboard( (Widget)w, False, GrabModeAsync, GrabModeAsync, event->xbutton.time );
-
- switch( what_button(w, mouse_x, mouse_y) )
- {
- case BUTTON_TROUGH_ABOVE:
- case BUTTON_TROUGH_BELOW:
- case BUTTON_KNOB:
- w->sb.savedValue = w->sb.value;
-
- height -= (2*arrow_height);
- y += arrow_height;
-
- last_above = w->sb.above;
- last_value = w->sb.value;
-
- w->sb.armed = ARM_KNOB;
- draw_knob(w, w->sb.above, w->sb.ss, w->sb.below);
-
- w->sb.above = mouse_y - (w->sb.ss / 2) - arrow_height;
- if( w->sb.above < 0 )
- {
- w->sb.above = 0;
- }
- else if( w->sb.above + w->sb.ss > height )
- {
- w->sb.above = height - w->sb.ss;
- }
- w->sb.below = (height - (w->sb.ss + w->sb.above));
-
- if( last_above != w->sb.above )
- {
- draw_knob(w, w->sb.above, w->sb.ss, w->sb.below);
-
- w->sb.value = value_from_pixel(w, w->sb.above);
- verify_values(w);
- CHECK(w);
-
- w->sb.lastY = mouse_y;
- w->sb.lastY = w->sb.above + arrow_height + (w->sb.ss / 2);
-
- if( w->sb.value != last_value )
- {
- call_callbacks( w, XmCR_DRAG, w->sb.value, event_y(w, event), event );
- }
- }
- break;
- }
- CHECK(w);
- }
-
- /*
- ** Abort
- */
- static void Abort(Widget widget, XEvent *event, String *parms, Cardinal *num_parms)
- {
- XlwScrollBarWidget w = (XlwScrollBarWidget)widget;
-
- DBUG(fprintf(stderr, "Abort:\n"));
-
- if( w->sb.armed != ARM_NONE )
- {
- if( w->sb.value != w->sb.savedValue )
- {
- w->sb.value = w->sb.savedValue;
-
- seg_pixel_sizes(w, &w->sb.above, &w->sb.ss, &w->sb.below);
- draw_knob(w, w->sb.above, w->sb.ss, w->sb.below);
-
- call_callbacks( w, XmCR_VALUE_CHANGED, w->sb.value, event_y(w, event), event );
- }
-
- switch( w->sb.armed )
- {
- case ARM_UP:
- redraw_up_arrow(w, False, False);
- break;
- case ARM_DOWN:
- redraw_down_arrow(w, False, False);
- break;
- }
-
- w->sb.armed = ARM_NONE;
-
- XtUngrabKeyboard( (Widget)w, event->xbutton.time );
- }
- }
-